# -*- coding: utf-8 -*-
#   __author__ = "Casey"     Email = 395280963qq.com
#   Data :2019/11/11  Python:3.7


from urllib.parse import urlencode
import requests
import time
import hmac
import hashlib
import execjs
import json
import re
import base64
from PIL import Image
import matplotlib.pyplot as plt
import threading

# 登陆并爬取知乎   仅供参考

s = requests.session()

def get_signature(grantType,clientId,source,timestamp):
    h = hmac.new(bytes("d1b964811afb40118a12068ff74a12f4",'utf-8'),bytes("",'utf-8'),hashlib.sha1)
    h.update((grantType+clientId+source+str(timestamp)).encode('utf-8'))
    return h.hexdigest()

def get_captcha(lang, headers):
    if lang == "cn":
        api = "https://www.zhihu.com/api/v3/oauth/captcha?lang=cn"
    else:
        api = "https://www.zhihu.com/api/v3/oauth/captcha?lang=en"

    ret = requests.get(api, headers=headers)
    cookies = ret.cookies
    show_captcha = re.search("true", ret.text)
    captcha = ""
    if show_captcha:
        img_res = requests.put(api, headers=headers,
                               cookies=cookies)  # 得带上第一步的cookie，否则返回，{u'code': 120002, u'name': u'ERR_CAPSION_TICKET_NOT_FOUND'}
        img_json = json.loads(img_res.text)
        img_data = img_json["img_base64"].replace("\n", "")
        with open("captcha.jpg", "wb") as i:
            i.write(base64.b64decode(img_data))
        img = Image.open("captcha.jpg")
        if lang == "cn":
            plt.imshow(img)
            print("点击图片中所有倒立的汉字，在命令行中按回车键提交")
            points = plt.ginput(7)  # 阻塞点击七次后返回(或者中途点击回车键返回)，返回包含坐标组的列表，格式：[(44.661290322580641, 49.951612903225794)]
            captcha = json.dumps({
                "img_size": [200, 44],
                "input_points": [[i[0] / 2, i[1] / 2] for i in points]  # 获取的坐标得除2
            })

        else:
            img_thread = threading.Thread(target=img.show)
            img_thread.setDaemon(True)
            img_thread.start()
            captcha = input("请输入图片里的验证码：")
        r = requests.post(api, headers=headers, data={"input_text": captcha}, cookies=cookies)  # 先提交验证码结果
        print('验证码>>>',r.text)
    return captcha, cookies


def get_xsrf(headers):
    url = "https://www.zhihu.com/"
    r = requests.get(url, headers=headers, allow_redirects=False)  # 禁止重定向时，cookies里面有xsrf参数
    xsrf = r.cookies["_xsrf"]
    # print(xsrf)

def login(lang,username,password):

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36", }

    # 准备表单数据
    timestamp = int(1000 * time.time())
    data_dict = {
        "client_id": "c3cef7c66a1843f8b3a9e6a1e3160e20",
        "grant_type": "password",
        "timestamp": timestamp,
        "source": "com.zhihu.web",
        "signature": "",
        "username": username,
        "password": password,
        "captcha": "",
        "lang": "en",
        "utm_source": "",
        "ref_source": "other_https://www.zhihu.com/signin?next=%2Fterms",
    }
    data_dict["signature"] = get_signature(data_dict["grant_type"], data_dict["client_id"], data_dict["source"],
                                           timestamp)
    data_dict["captcha"], cookies = get_captcha(lang, headers)
    print(data_dict)
    # 将表单数据加密
    with open("encrypt.js",'r',encoding='utf-8') as f:
        js = execjs.compile(f.read().replace('\xa0',''),cwd=r'C:\Users\longkexu\AppData\Roaming\npm\node_modules')  #传入unicode字符
        data = js.call(u'b',urlencode(data_dict)) #data_dict为表单数据
        # print(data)

    xsrf = get_xsrf(headers)
    header = {
        "content-type": "application/x-www-form-urlencoded",
        'x-zse-83': '3_2.0',
        "x-xsrftoken": xsrf,
    }
    headers.update(header)
    sign_url = "https://www.zhihu.com/api/v3/oauth/sign_in"
    response = s.post(url=sign_url, headers=headers, data=data, cookies=cookies)  # cookies["capsion_ticket"]不能少
    # print(response.status_code)
    print(json.loads(response.text))


if __name__ == "__main__":
    username = input('请输入你的账户>>>')
    password = input('请输入你的密码>>>')
    login("en",username,password)  # 也可以为en 和 cn


